package org.beanutopia.slot;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ReferenceMap;
import org.beanutopia.exception.PropertyDefinitionException;
import org.beanutopia.function.Injection;

/**
 * @author: Yardena
* @date: Oct 27, 2009 3:26:46 PM
*/
public final class ExtraSlot<V> implements Slot<Object, V> {
  private transient final ReferenceMap<Object,V> values = new ReferenceMap<Object,V>(com.google.common.base.ReferenceType.WEAK, com.google.common.base.ReferenceType.STRONG);

  public Function<Object, V> getProjection() {
    return new Function<Object, V>() {
      public V apply(Object object) {
        return values.get(object);
      }
    };
  }

  public Injection<Object, V> getInjection() {
    return new Injection<Object, V>() {
      public void apply(Object object, V value) {
        if (value == null)
          values.remove(object);
        else
          values.put(object, value);
      }
    };
  }

  public Slot<Object, V> initialize() throws PropertyDefinitionException {
    return this;
  }

  public Predicate<Object> supported() {
    return com.google.common.base.Predicates.alwaysTrue();
  }
}
